/**
 * Copyright 2008 Adam Ruggles.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package kiff.action.admin;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Inject;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable;
import com.opensymphony.xwork2.validator.annotations.Validations;
import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator;

import kiff.action.AbstractCRUDAction;
import kiff.entity.Forum;
import kiff.entity.ForumAcl;
import kiff.enumerator.ForumStatus;
import kiff.interceptor.InputErrorsAware;
import kiff.service.CoreService;
import kiff.service.ForumService;

/**
 * Admin Forum Action.  Controls the administration of forums.
 * @author Adam
 * @version $Id$
 * 
 * Created on Nov 3, 2008 at 7:29:54 PM 
 */
@Validations(
		requiredStrings = {
				@RequiredStringValidator(fieldName = "name",
						message = "Required Field.", key = "validation.required"),
				@RequiredStringValidator(fieldName = "description",
						message = "Required Field.", key = "validation.required")
		} 
)
public class ForumAction extends AbstractCRUDAction<Forum> implements Preparable, ModelDriven<Forum>, InputErrorsAware {
	/**
	 * Serial Version UID.
	 */
	private static final long serialVersionUID = -1796435479689732996L;

	/**
	 * Forum ACL ID. Since OGNL doesn't support generics I am forced not to be able to use the permissions.id field.
	 */
	private Integer aclId;

	/**
	 * Entity ID.  Since OGNL doesn't support generics I am forced not to be able to use the forum id field.
	 */
	private Integer eid;

	/**
	 * Forum Entity used to transport data from the view to the service layer.
	 */
	private Forum forum;

	/**
	 * A List of forums used on the add and edit pages.
	 */
	private List<Forum> forumList;

	/**
     * The <code>Logger</code> is used by the application to generate a log messages.
     */
    private final Logger logger = LoggerFactory.getLogger(ForumAction.class);

	/**
	 * Parent ID. Since OGNL doesn't support generics I am forced not to be able to use the parent.id field.
	 */
	private Integer pid;

	/**
	 * Returns aclId.
	 * @return the aclId.
	 */
	public Integer getAclId() {
		return aclId;
	}

	/**
	 * Returns eid.
	 * @return the eid.
	 */
	public Integer getEid() {
		return eid;
	}

	/**
	 * Returns forumList.
	 * @return the forumList.
	 */
	public List<Forum> getForumList() {
		return forumList;
	}

	/**
	 * {@inheritDoc}
	 * @see com.opensymphony.xwork2.ModelDriven#getModel()
	 */
	public Forum getModel() {
		return forum;
	}

	/**
	 * Returns pid.
	 * @return the pid.
	 */
	public Integer getPid() {
		return pid;
	}

	/**
	 * {@inheritDoc}
	 * @see com.opensymphony.xwork2.Preparable#prepare()
	 */
	public void prepare() throws Exception {
		logger.debug("Calling Prepare");
		if (forum == null) {
			forum = new Forum();
			ForumAcl acl = new ForumAcl();
			acl.setId(getAclId());
			forum.setPermissions(acl);
			forum.setParent(new Forum());
			forum.getParent().setId(getPid());
			if (getEid() != null) {
				forum.setId(getEid());
			}
		}
	}

	/**
	 * Prepares the action for the add operation.
	 * @throws Exception If an error occurs preparing the add operation.
	 */
	public void prepareAdd() throws Exception {
		logger.debug("Calling Prepare Add");
		forumList = ((ForumService) service).findByStatus(ForumStatus.ACTIVE, ForumStatus.LOCKED);
	}

	/**
	 * Prepares the action for the edit operation.
	 * @throws Exception If an error occurs preparing the edit operation.
	 */
	public void prepareEdit() throws Exception {
		logger.debug("Calling Prepare Edit");
		if (getEid() == null) {
			throw new IllegalArgumentException("No eid when trying to edit a forum");
		}
		forum = service.find(getEid());
		forumList = ((ForumService) service).findByStatus(ForumStatus.ACTIVE, ForumStatus.LOCKED);
		forumList.remove(forum);
	}

	/**
	 * {@inheritDoc}
	 * @see kiff.interceptor.InputErrorsAware#prepareInputErrors()
	 */
	public void prepareInputErrors() {
		logger.debug("Calling Input Errors [{}]", getActionMethod());
		forumList = ((ForumService) service).findByStatus(ForumStatus.ACTIVE, ForumStatus.LOCKED);
		if (UPDATE.equals(getActionMethod())) {
			Forum toRemove = null;
			for (Forum f : forumList) {
				if (f.getId().equals(forum.getId())) {
					toRemove = f;
					break;
				}
			}
			forumList.remove(toRemove);
		}
	}

	/**
	 * Sets aclId.
	 * @param aclId the aclId to set.
	 */
	public void setAclId(final Integer aclId) {
		this.aclId = aclId;
	}

	/**
	 * Sets eid.
	 * @param eid the eid to set.
	 */
	public void setEid(final Integer eid) {
		this.eid = eid;
	}

	/**
	 * Sets pid.
	 * @param pid the pid to set.
	 */
	public void setPid(final Integer pid) {
		this.pid = pid;
	}

	/**
	 * {@inheritDoc}
	 * @see kiff.action.AbstractCRUDAction#setService(kiff.service.CoreService)
	 */
	@Inject
	public void setService(final CoreService<Forum> service) {
		this.service = service;
	}
}
